using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using TimeWar.Lib.Animation;
using Microsoft.Xna.Framework.Graphics;
using TimeWar.Lib.Camera;

namespace TimeWar.Lib
{
    public enum ModelType
    {
        Static,
        Animated,
    }

    public class TimeWarModel : ISceneNode
    {
        #region attributes

        protected Vector3 m_currPosition;
        protected Vector3 m_prevPosition;
        protected ModelType m_modelType = ModelType.Static;
        Model m_currentModel;
        AnimationPlayer m_animationPlayer = null;
        CameraBase m_currCamera = null;

        #endregion attributes

        public TimeWarModel(ModelType pType)
        {
            m_modelType = pType;

        }


        #region ISceneNode Members

        public Vector3 Position
        {
            get { return m_currPosition; }
            set
            {
                m_prevPosition = m_currPosition;
                m_currPosition = value;
            }
        }

        public Vector3 PreviousPosition
        {
            get { return m_prevPosition; }
        }

        public void LoadContent(Game timeWarGameObj, String contentLocation)
        {
            // Load the model.
            m_currentModel = timeWarGameObj.Content.Load<Model>("dude");

            //Load behaviour dependent on model type:
            if (m_modelType == ModelType.Animated)
            {
                #region Animation logic

                // Look up our custom skinning information.
                SkinningData skinningData = m_currentModel.Tag as SkinningData;

                if (skinningData == null)
                    throw new InvalidOperationException
                        ("This model does not contain a SkinningData tag.");

                // Create an animation player, and start decoding an animation clip.
                m_animationPlayer = new AnimationPlayer(skinningData);

                AnimationClip clip = skinningData.AnimationClips["Take 001"];

                m_animationPlayer.StartClip(clip);

                #endregion Animation logic

            }
            
        }

        #endregion

        #region IDrawable Members

        public void Draw(GameTime gameTime)
        {
            Matrix[] bones;

            if (m_modelType == ModelType.Animated)
            {
                bones = m_animationPlayer.GetSkinTransforms();
            }
            else
            {
                bones = new Matrix[m_currentModel.Bones.Count];
                for (int i = 0; i < m_currentModel.Bones.Count; i++)
                {
                    bones[i] = m_currentModel.Bones[i].Transform;
                }
            }

            // Render the skinned mesh.
            foreach (ModelMesh mesh in m_currentModel.Meshes)
            {
                foreach (Effect effect in mesh.Effects)
                {
                    effect.Parameters["Bones"].SetValue(bones);
                    effect.Parameters["View"].SetValue(m_currCamera.ViewMatrix);
                    effect.Parameters["Projection"].SetValue(m_currCamera.ProjectionMatrix);
                }

                mesh.Draw();
            }
        }

        public int DrawOrder
        {
            get { throw new NotImplementedException(); }
        }

        public event EventHandler DrawOrderChanged;

        public bool Visible
        {
            get { throw new NotImplementedException(); }
        }

        public event EventHandler VisibleChanged;

        #endregion

        public CameraBase Camera
        {
            set { m_currCamera = value; }
        }


        #region IUpdateable Members

        public bool Enabled
        {
            get { throw new NotImplementedException(); }
        }

        public event EventHandler EnabledChanged;

        public void Update(GameTime gameTime)
        {
            //throw new NotImplementedException();

            if (m_modelType == ModelType.Animated)
            {
                m_animationPlayer.Update(gameTime.ElapsedGameTime, true, Matrix.Identity);
            }

        }

        public int UpdateOrder
        {
            get { throw new NotImplementedException(); }
        }

        public event EventHandler UpdateOrderChanged;

        #endregion
    }
}